home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_081 / icon / icon1.txt < prev    next >
Text File  |  1992-05-06  |  7KB  |  147 lines

  1.  
  2.                          Programming in Icon
  3.                        A Simple Search Program
  4.                      (C) 1987 by Larry Phillips
  5.  
  6.   I decided to write a search program that mimics the Amiga supplied SEARCH to
  7. see how Icon compared to other languages. The minimal search, one that does not
  8. print out the line numbers, and which is case sensitive, is as follows:
  9.  
  10. procedure main(args)
  11.   in := open (args[1]) | stop("Can't open input file")
  12.   pattern := args[2]
  13.   while line := read(in) do
  14.     if find (pattern,line) then
  15.       write(line)
  16.     else next
  17. end
  18.  
  19. A few words of explanation are in order.
  20.  
  21. Arguments are passed as a list of strings. args[1] is the first item in the
  22. list, and is the file name. The line that opens the file assigns the file
  23. handle to the variable 'in', if successful. If not successful, the program will
  24. stop with a message, "Can't open input file." An "english" reading of the line
  25. would be "Either open the file or stop and print a message". Note that even
  26. though I opened the file, I have not closed it anywhere. This is because all
  27. files are closed when the program terminates. If you are working with a large
  28. number of files, it is good practice to close them as they become unnecessary.
  29.  
  30. The second element of the argument list is the search string. I have added the
  31. extra assignment of the search string to the variable 'pattern' for clarity
  32. only, and could as easily have used 'args[2]' later on in the 'if find..'
  33. statement.
  34.  
  35. The 'while..' statement will read lines from the specified file until either
  36. EOF or an error condition is encountered, and will assign the value read to the
  37. variable 'line'. The while statement operates much like the while in C, in that
  38. it will execute the next line until the terminating condition is met. Note that
  39. the 'if' statement following the 'while' includes the 'write', which is on the
  40. next line for clarity only. It could have been written as:
  41.  
  42. if find (pattern,line) then write (line)
  43.  
  44. The 'find' function returns the position of one string within another. In this
  45. case we are only interested in the success or failure of the 'find' statement,
  46. and if successful, we write the line to the screen. If it fails, the 'else'
  47. statement executes and the 'next' takes us back, continuing with the 'while'
  48. statement.
  49.  
  50. The 'end' tells us that this is the end of the procedure.
  51.  
  52. Since we might be interested in the line number in which any matches occur, and
  53. since we want to make the search case insensitive, I modified the program to
  54. handle these criteria. Now bear in mind that I am strictly a novice Icon
  55. programmer, and that there are undoubtedly better ways to do this. The modified
  56. code looks like this:
  57.  
  58. procedure main(args)
  59.   i := 0
  60.   in := open (args[1]) | stop("Can't open input file")
  61.   pattern := args[2]
  62.   while line := read(in) do {
  63.     i +:= 1
  64.     if find (pattern,map(line,&ucase,&lcase)) then
  65.       write(i || " " || line)
  66.     else next
  67.     }
  68. end
  69.  
  70. Notice that that we are using a variable to count lines. The use of the
  71. variable 'i' is straightforward, but notice that we now have two statements to
  72. perform within the 'while' control block. The curly brace is used to logically
  73. group the lines as part of the 'while' statement. It's exactly the same as in a
  74. C program.
  75.  
  76. The case insensitivity is provided by modifying the 'find'. The 'map' function
  77. will cause any characters in 'line' that appear in the second string to be
  78. replaced with the corresponding characters in the third string. As an example,
  79. the statement:
  80.  
  81. write map("hello there","e","-")
  82.  
  83. will cause the string "h-llo th-r-" to be written to the screen.
  84.  
  85. The mapping strings in this case are special strings called 'csets', which are
  86. sets of unique characters. An example of a cset would be the set of vowels, and
  87. can be generated with the statement:
  88.  
  89. vowel := 'aeiou'
  90.  
  91. The exact same set can be made with either:
  92.  
  93. vowel := 'uoiea' 
  94.  
  95.   or
  96.  
  97. vowel := 'aaaeeeiiiooouuu'
  98.  
  99. Since the characters are unique, and since the idea of order in a cset in
  100. meaningless, the same cset is produced in all three cases. In the example
  101. program, there are two csets used, &lcase and &ucase. These are "built in"
  102. csets that represent the set of all lower case characters and the set of all
  103. upper case characters, respectively.
  104.  
  105. The function 'map(line,&ucase,&lcase)' will return a string that consists of
  106. whatever is contained in the variable 'line', but with all the upper case
  107. characters mapped to lower case. The 'find' function then, will perform its
  108. function on the mapped string. To be truly general, and to allow the search
  109. string to be in mixed case, 'map' should be applied to the variable 'pattern'.
  110. This is best done outside the loop to save time, since it nees to be done only
  111. once. To implement this, we would change the line 'pattern := args[2]' to read
  112. 'pattern := map (args[2],&ucase,&lcase)'.
  113.  
  114. The last change is in the line we write to the screen when the find is
  115. successful. The '||' operator is the operator to concatenate strings.
  116. Note that due to Icon's automatic type conversion, we do not have to
  117. explicitly convert the variable 'i', which we have been using as a numeric
  118. counter, into a string. The type is converted for us, and the resulting line
  119. will consist of the line number followed by a space, followed by the line
  120. itself.
  121.  
  122. So, that's it. Now for the burning questions. How big is the resulting code,
  123. and how is the speed? How long does it take to compile?
  124.  
  125. Icon is not a true "compiled" langauge, nor is it a true "iterpreted" language.
  126. The size of the resulting program is only 3484 bytes, but when executed, the
  127. run-time module (iconx) must be loaded in, and it is nearly 100K. On a 1.5 meg
  128. system, with Icon kept in RAM:, the compile speed is lightning fast, taking
  129. (for this program) just over 2 seconds.
  130.  
  131. The speed is surprising for such a high level language. I have a file I search
  132. on a regular basis that is about 120K. For the test, I used a stopwatch, and
  133. copied the Amigados SEARCH command into RAM: so that load times would not be
  134. dependent upon device speed. The results were:
  135.  
  136. Amigados SEARCH -- about 51 seconds
  137. Icon search     -- about 39 seconds
  138.  
  139. Note that the Icon search command, if you had it on disk alnong with 'iconx',
  140. would have taken a longer to load, and the results would have been a lot
  141. closer.
  142.  
  143. I feel that as a high level language, Icon is a very respectable language for
  144. "quick and dirty" or "one time" programs, especially in the area of text
  145. processing.  The price is right (it's PD), and it's relatively easy to learn.
  146.  
  147.